import { Request, Response, NextFunction } from 'express';
import prometheusService from '@services/prometheus';
import logger from '@utils/logger';

/**
 * Prometheus 指标控制器
 */
class PrometheusController {
  /**
   * 执行 Prometheus 查询
   */
  async query(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { query, time } = req.query;

      if (!query) {
        res.status(400).json({
          success: false,
          message: 'Query parameter is required',
        });
        return;
      }

      const result = await prometheusService.query({
        query: query as string,
        time: time as string,
      });

      res.status(200).json({
        success: true,
        data: result,
      });
    } catch (error) {
      logger.error('Failed to execute Prometheus query:', error as Error);
      next(error);
    }
  }

  /**
   * 执行 Prometheus 范围查询
   */
  async queryRange(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { query, start, end, step = '60s' } = req.query;

      if (!query || !start || !end) {
        res.status(400).json({
          success: false,
          message: 'Query, start and end parameters are required',
        });
        return;
      }

      const result = await prometheusService.queryRange({
        query: query as string,
        start: start as string,
        end: end as string,
        step: step as string,
      });

      res.status(200).json({
        success: true,
        data: result,
      });
    } catch (error) {
      logger.error('Failed to execute Prometheus range query:', error as Error);
      next(error);
    }
  }

  /**
   * 获取系统健康指标
   */
  async getSystemHealth(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const health = await prometheusService.getSystemHealth();

      res.status(200).json({
        success: true,
        data: health,
      });
    } catch (error) {
      logger.error('Failed to get system health metrics:', error as Error);
      next(error);
    }
  }

  /**
   * 获取应用性能指标
   */
  async getApplicationMetrics(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const metrics = await prometheusService.getApplicationMetrics();

      res.status(200).json({
        success: true,
        data: metrics,
      });
    } catch (error) {
      logger.error('Failed to get application metrics:', error as Error);
      next(error);
    }
  }

  /**
   * 获取时间序列数据
   */
  async getTimeSeriesData(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { query, start, end, step = '60s' } = req.query;

      if (!query) {
        res.status(400).json({
          success: false,
          message: 'Query parameter is required',
        });
        return;
      }

      const startDate = start ? new Date(start as string) : new Date(Date.now() - 3600000);
      const endDate = end ? new Date(end as string) : new Date();

      const data = await prometheusService.getTimeSeriesData(
        query as string,
        startDate,
        endDate,
        step as string
      );

      res.status(200).json({
        success: true,
        data,
      });
    } catch (error) {
      logger.error('Failed to get time series data:', error as Error);
      next(error);
    }
  }

  /**
   * 获取所有标签
   */
  async getLabels(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const labels = await prometheusService.getLabels();

      res.status(200).json({
        success: true,
        data: labels,
      });
    } catch (error) {
      logger.error('Failed to get labels:', error as Error);
      next(error);
    }
  }

  /**
   * 获取标签值
   */
  async getLabelValues(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { label } = req.params;

      if (!label) {
        res.status(400).json({
          success: false,
          message: 'Label parameter is required',
        });
        return;
      }

      const values = await prometheusService.getLabelValues(label);

      res.status(200).json({
        success: true,
        data: values,
      });
    } catch (error) {
      logger.error(`Failed to get values for label ${req.params.label}:`, error as Error);
      next(error);
    }
  }

  /**
   * 获取指标列表
   */
  async getMetrics(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const metrics = await prometheusService.getMetrics();

      res.status(200).json({
        success: true,
        data: metrics,
      });
    } catch (error) {
      logger.error('Failed to get metrics:', error as Error);
      next(error);
    }
  }

  /**
   * 获取实例列表
   */
  async getInstances(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const instances = await prometheusService.getInstances();

      res.status(200).json({
        success: true,
        data: instances,
      });
    } catch (error) {
      logger.error('Failed to get instances:', error as Error);
      next(error);
    }
  }

  /**
   * 获取服务列表
   */
  async getServices(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const services = await prometheusService.getServices();

      res.status(200).json({
        success: true,
        data: services,
      });
    } catch (error) {
      logger.error('Failed to get services:', error as Error);
      next(error);
    }
  }

  /**
   * 检查 Prometheus 健康状态
   */
  async checkHealth(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const health = await prometheusService.checkHealth();

      res.status(200).json({
        success: true,
        data: health,
      });
    } catch (error) {
      logger.error('Failed to check Prometheus health:', error as Error);
      next(error);
    }
  }

  /**
   * 获取告警规则
   */
  async getAlertRules(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const rules = await prometheusService.getAlertRules();

      res.status(200).json({
        success: true,
        data: rules,
      });
    } catch (error) {
      logger.error('Failed to get alert rules:', error as Error);
      next(error);
    }
  }
}

export default new PrometheusController();
